<?php

/**
 * 
 * Enter description here ...
 * @author taras
 *
 */
class gApp extends gCoreObject
{
	private static $configuration = array(
		'debug' => true,
		'dborepsistent' => true,
		'dboconf'=>null,
		'app_path'=> _APP_PATH,
		'app_url' => 'app',
		'com_path' => 'components',
		'mod_path'=> 'modules',
		'mod_url' => null,
		'viewpath' => 'views',
		'viewurl'  => 'views',
		'layout' => 'default'
	);
	
	private $_modules = array();
	/**
	 * (non-PHPdoc)
	 * @see gKernel::init()
	 */
	public function init()
	{
		if( defined('_GEPARD_APPCONF'))
		{
			$this->parseConf(_GEPARD_APPCONF);
		}
		if( !defined('_APP_PATH'))
		{
		throw new gException('Application path is not defined', gError::CORE);
		}
	}
	
	public function start()
	{
		
	}
	
	/**
	 * 
	 * Enter description here ...
	 * @param string_type $controller
	 * @param string $action
	 */
	public function dispatch($controller,$action = 'index')
	{
		$module = $this->getModule($controller);
		if( !method_exists($module, $action) && !method_exists($module, '__call'))
		{
			throw new gException('Action not found', gError::NOT_FOUND);
		}
		$module->preDispatch();
		call_user_func_array(array($module,$action), array());
		$module->postDispatch();
	}
	
	/**
	 * Returns self application path
	 * Enter description here ...
	 */
	public static function getPath()
	{
		return _APP_PATH;
	}
	
	
	/**
	 * 
	 * Enter description here ...
	 * @param unknown_type $name
	 */
	public static function getAsPath($name)
	{
        $param = self::get($name);
        if( !preg_match("/^([A-z]{1}\:)/",$param) && !preg_match("/^(\/{1})/",$param) ){
            $param = realpath(_APP_PATH . $param);
        }
        $lindex = strlen($param)-1;
        if( $param[$lindex] != '/' || $param !='\\')
        {
            $param .= DIRECTORY_SEPARATOR;
        }
        return $param;
	}

	public static function getModPath($modname)
	{
		return self::getAsPath('mod_path') . $modname . DIRECTORY_SEPARATOR;
	}

	public static function getModUrl($modname)
	{
		return self::getAsUrl('mod_url') . $modname . '/';
	}


	/**
	 * 
	 * Enter description here ...
	 * @param unknown_type $name
	 */
    public static function getAsUrl($name)
    {
        $val = self::get('viewurl');
        if( $val[0] == '/' || preg_match('/^http\:/',$val) )
        {
            return $val;
        }
        else
        {
            return _APP_URL . $val . '/';
        }
    }

    /**
	 * 
	 * Enter description here ...
	 * @param unknown_type $filename
	 * @throws gException
	 */
	public static function parseConf($filename)
	{
		if( file_exists($filename) )
		{
			require_once $filename;
		}
		else
		{
			throw new gException('Cannot find application configuration file', gError::FILE_NOT_FOUND);
		}
	}
	
	/**
	 * 
	 * Enter description here ...
	 * @param unknown_type $filename
	 */
	public function parseIniConf($filename)
	{
		
	}
	/**
	 * 
	 * Enter description here ...
	 * @param unknown_type $filename
	 */	
	public function parseXmlConf($filename)
	{
		
	}
    
    public function bindComponent($name)
    {
        self::loadComponent($name);
        $this->core->createObject($name);
    }

    public static function loadComponent($name)
    {
        $path = self::getAsPath('com_path');
        $file = $path . $name . '.php';
        if( file_exists($file))
        {
            require_once $file;
        }
        else
        {
            throw new Exception('Cannot found component (' . $name . ')', gError::FILE_NOT_FOUND);
        }

    }

    public static function includeComponentFile($name,$file)
    {
        $path = self::getAsPath('com_path');
        $file = $path . $name . DIRECTORY_SEPARATOR . $file . '.php';
        if(file_exists($file))
        {
            require_once $file;
        }
        else
        {
            throw new gException('Cannot found component package file ('.$name.','.$file.')', gError::FILE_NOT_FOUND);
        }
    }
    
    /**
     * 
     * Enter description here ...
     */
    public function listen()
    {
		
    }
    

    /**
	 * 
	 * Enter description here ...
	 * @param unknown_type $name
	 */
	public function getModule($name)
	{
		if( !is_array($name) && array_key_exists($name,$this->_modules))
		{
			return $this->_modules[$name];
		}
		else
		{
			if( is_array($name)) {
				$pathname = $name[0];
				$name = $name[1];
			} else $pathname = $name;
			self::loadModule($pathname);
			$classname = 'g'.ucfirst($name).'Controller';
			$this->_modules[$name] = new $classname($this->core);
			$this->_modules[$name]->init();
			return $this->_modules[$name];
		}
	}
	
	/**
	 * 
	 * Enter description here ...
	 * @param unknown_type $name
	 * @throws Exception
	 */
	public static function loadModule( $name )
	{
		$path = self::getAsPath('mod_path') . $name . DIRECTORY_SEPARATOR;
		foreach (glob("$path/*.php") as $filename)
		{
			include $filename;
		}
		return true;
	}

    public static function loadModel($modname, $model = 'default')
    {
        
    }

    public function callaction($controller,$action='index')
    {
        $module = $this->getModule($controller);
        if( !in_array($action,  get_class_methods(get_class($module))))
        {
            throw new gException('Method not found in controller ' . $controller, gError::NOT_FOUND);
        }
        if( !method_exists($module, $action))
        {
        	throw new gException('Action not found', gError::NOT_FOUND);
        }
        call_user_func_array(array($module,$action), array());
    }
	
	/**
	 * 
	 * Enter description here ...
	 * @param unknown_type $key
	 * @param unknown_type $value
	 */
	public static function set($key,$value)
	{
            self::$configuration[$key] = $value;
	}
	/**
	 * 
	 * Enter description here ...
	 * @param unknown_type $key
	 */	
	public static function get($key)
	{
        if (array_key_exists($key, self::$configuration))
        {
            return self::$configuration[$key];
        }
        return false;
	}
	
	
	public function shutdown()
	{
		if( $this->core->hasLoaded('dbo'))
		{
			$this->core->dbo->disconnect();
		}
	}
	
	
}